package services

import (
	"errors"
	"fmt"
	"time"
	Init "vulnmain/Init"
	"vulnmain/models"
)

type VulnService struct{}

type VulnCreateRequest struct {
	Title       string  `json:"title" binding:"required"`
	Description string  `json:"description"`
	VulnType    string  `json:"vuln_type" binding:"required"`
	Severity    string  `json:"severity" binding:"required"`
	Source      string  `json:"source"`
	CVEID       string  `json:"cve_id"`
	CNNVDID     string  `json:"cnnvd_id"`
	CVSSScore   float64 `json:"cvss_score"`
	POC         string  `json:"poc"`
	Solution    string  `json:"solution"`
	References  string  `json:"references"`
	AssetID     uint    `json:"asset_id" binding:"required"`
	ProjectID   uint    `json:"project_id" binding:"required"`
	AssigneeID  *uint   `json:"assignee_id"`
	Tags        string  `json:"tags"`
}

type VulnUpdateRequest struct {
	Title           string `json:"title"`
	Description     string `json:"description"`
	VulnType        string `json:"vuln_type"`
	Severity        string `json:"severity"`
	Status          string `json:"status"`
	POC             string `json:"poc"`
	Solution        string `json:"solution"`
	References      string `json:"references"`
	AssigneeID      *uint  `json:"assignee_id"`
	Tags            string `json:"tags"`
	RejectReason    string `json:"reject_reason"`
	Comment         string `json:"comment"`
	ResubmittedAt   string `json:"resubmitted_at"`
	ResubmittedBy   *uint  `json:"resubmitted_by"`
}

type VulnListRequest struct {
	Page       int    `form:"page" binding:"min=1"`
	PageSize   int    `form:"page_size" binding:"min=1,max=100"`
	Keyword    string `form:"keyword"`
	Title      string `form:"title"`
	VulnType   string `form:"vuln_type"`
	Severity   string `form:"severity"`
	Status     string `form:"status"`
	Source     string `form:"source"`
	AssetID    *uint  `form:"asset_id"`
	ProjectID  *uint  `form:"project_id"`
	ReporterID *uint  `form:"reporter_id"`
	AssigneeID *uint  `form:"assignee_id"`
	// 权限控制字段
	CurrentUserID   uint   `form:"-"`
	CurrentUserRole string `form:"-"`
}

type VulnListResponse struct {
	Vulns           []models.Vulnerability `json:"vulns"`
	Vulnerabilities []models.Vulnerability `json:"vulnerabilities"`
	Total           int64                  `json:"total"`
	Page            int                    `json:"page"`
	PageSize        int                    `json:"page_size"`
	CurrentPage     int                    `json:"current_page"`
	TotalPages      int                    `json:"total_pages"`
}

type AuditRequest struct {
	Status     string  `json:"status" binding:"required"`
	Comment    string  `json:"comment"`
	Severity   string  `json:"severity"`
	CvssScore  float64 `json:"cvss_score"`
	AssigneeID *uint   `json:"assignee_id"`
}

// CreateVuln 创建漏洞
func (s *VulnService) CreateVuln(req *VulnCreateRequest, reporterID uint) (*models.Vulnerability, error) {
	db := Init.GetDB()

	// 验证资产是否存在
	var asset models.Asset
	if err := db.Where("id = ?", req.AssetID).First(&asset).Error; err != nil {
		return nil, errors.New("资产不存在")
	}

	// 验证项目是否存在且未过期
	if req.ProjectID != 0 {
		var project models.Project
		if err := db.Where("id = ?", req.ProjectID).First(&project).Error; err != nil {
			return nil, errors.New("项目不存在")
		}

		// 检查项目是否过期
		if project.EndDate != nil && time.Now().After(*project.EndDate) {
			return nil, errors.New("项目已过期，无法添加漏洞")
		}
	}

	// 验证分配人是否存在(如果指定)
	if req.AssigneeID != nil {
		var assignee models.User
		if err := db.Where("id = ?", *req.AssigneeID).First(&assignee).Error; err != nil {
			return nil, errors.New("指定的分配人不存在")
		}
	}

	vuln := models.Vulnerability{
		Title:       req.Title,
		Description: req.Description,
		VulnType:    req.VulnType,
		Severity:    req.Severity,
		Status:      "pending",
		CVEID:       req.CVEID,
		ProjectID:   req.ProjectID,
		AssetID:     req.AssetID,
		ReporterID:  reporterID,
		AssigneeID:  req.AssigneeID,
		SubmittedAt: time.Now().Truncate(time.Second), // 设置提交时间，精确到秒
		Tags:        req.Tags,
	}

	if err := db.Create(&vuln).Error; err != nil {
		return nil, errors.New("创建漏洞失败")
	}

	// 创建时间线记录
	s.addTimeline(vuln.ID, reporterID, "created", "漏洞已创建")

	// 如果指定了分配人，创建分配记录
	if req.AssigneeID != nil {
		s.addTimeline(vuln.ID, reporterID, "assigned", "漏洞已分配")
	}

	// 重新查询漏洞信息(包含关联数据)
	db.Preload("Asset").Preload("Project").Preload("Reporter").Preload("Assignee").Preload("Rejector").Preload("Resubmitter").Where("id = ?", vuln.ID).First(&vuln)

	// 更新项目统计信息
	if req.ProjectID != 0 {
		projectService := &ProjectService{}
		if err := projectService.UpdateProjectStats(req.ProjectID); err != nil {
			// 统计更新失败不影响漏洞创建，只记录错误
			// 可以考虑添加日志记录
		}
	}

	// 发送邮件通知给指派的研发工程师
	if req.AssigneeID != nil {
		go func() {
			var assignee models.User
			if err := db.First(&assignee, *req.AssigneeID).Error; err == nil && assignee.Email != "" {
				assigneeName := assignee.RealName
				if assigneeName == "" {
					assigneeName = assignee.Username
				}

				projectName := ""
				if vuln.ProjectID != 0 {
					projectName = vuln.Project.Name
				}

				if err := SendVulnAssignedNotification(req.Title, projectName, assigneeName, assignee.Email, req.Severity); err != nil {
					// 记录邮件发送失败的日志，但不影响漏洞创建
					fmt.Printf("发送漏洞分派通知邮件失败: %v\n", err)
				}
			}
		}()
	}

	return &vuln, nil
}

// GetVulnByID 根据ID获取漏洞
func (s *VulnService) GetVulnByID(vulnID uint, userID uint, userRole string) (*models.Vulnerability, error) {
	db := Init.GetDB()

	var vuln models.Vulnerability
	if err := db.Preload("Asset").Preload("Project").Preload("Reporter").Preload("Assignee").
		Preload("Fixer").Preload("Retester").Preload("Rejector").Preload("Resubmitter").Preload("Attachments").Preload("Comments.User").
		Preload("Timeline.User").Where("id = ?", vulnID).First(&vuln).Error; err != nil {
		return nil, errors.New("漏洞不存在")
	}

	// 基于角色的权限控制
	canAccess := false
	switch userRole {
	case "super_admin":
		// 超级管理员能看到所有漏洞
		canAccess = true
	case "security_engineer":
		// 安全工程师可以看到自己创建的漏洞，或者自己负责的项目的漏洞，或者自己参与项目的漏洞
		if vuln.ReporterID == userID {
			canAccess = true
		} else {
			// 检查是否是项目负责人
			var project models.Project
			if err := db.Where("id = ? AND owner_id = ?", vuln.ProjectID, userID).First(&project).Error; err == nil {
				canAccess = true
			} else {
				// 检查是否是项目成员
				var memberCount int64
				db.Model(&models.ProjectMember{}).Where("project_id = ? AND user_id = ?", vuln.ProjectID, userID).Count(&memberCount)
				if memberCount > 0 {
					canAccess = true
				}
			}
		}
	case "dev_engineer":
		// 研发工程师可以看到分配给自己的漏洞，或者自己负责的项目的漏洞，或者自己参与项目的漏洞
		if vuln.AssigneeID != nil && *vuln.AssigneeID == userID {
			canAccess = true
		} else {
			// 检查是否是项目负责人
			var project models.Project
			if err := db.Where("id = ? AND owner_id = ?", vuln.ProjectID, userID).First(&project).Error; err == nil {
				canAccess = true
			} else {
				// 检查是否是项目成员
				var memberCount int64
				db.Model(&models.ProjectMember{}).Where("project_id = ? AND user_id = ?", vuln.ProjectID, userID).Count(&memberCount)
				if memberCount > 0 {
					canAccess = true
				}
			}
		}
	}

	if !canAccess {
		return nil, errors.New("漏洞不存在")
	}

	return &vuln, nil
}

// UpdateVuln 更新漏洞信息
func (s *VulnService) UpdateVuln(vulnID uint, req *VulnUpdateRequest, userID uint, userRole string) (*models.Vulnerability, error) {
	db := Init.GetDB()

	var vuln models.Vulnerability
	if err := db.Where("id = ?", vulnID).First(&vuln).Error; err != nil {
		return nil, errors.New("漏洞不存在")
	}

	// 保存原始状态，用于邮件通知
	oldStatus := vuln.Status

	// 基于角色的权限控制和字段更新
	switch userRole {
	case "super_admin":
		// 超级管理员可以更新所有字段
		if req.Title != "" {
			vuln.Title = req.Title
		}
		if req.Description != "" {
			vuln.Description = req.Description
		}
		if req.VulnType != "" {
			vuln.VulnType = req.VulnType
		}
		if req.Severity != "" {
			vuln.Severity = req.Severity
		}
		if req.Status != "" {
			vuln.Status = req.Status
		}
		if req.Tags != "" {
			vuln.Tags = req.Tags
		}

	case "security_engineer":
		// 安全工程师只能更新自己创建的漏洞或项目内的漏洞
		if vuln.ReporterID != userID {
			// 检查是否是项目成员
			var memberCount int64
			db.Model(&models.ProjectMember{}).Where("project_id = ? AND user_id = ?", vuln.ProjectID, userID).Count(&memberCount)
			if memberCount == 0 {
				return nil, errors.New("无权限编辑此漏洞")
			}
		}

		// 安全工程师可以更新大部分字段
		if req.Title != "" {
			vuln.Title = req.Title
		}
		if req.Description != "" {
			vuln.Description = req.Description
		}
		if req.VulnType != "" {
			vuln.VulnType = req.VulnType
		}
		if req.Severity != "" {
			vuln.Severity = req.Severity
		}
		if req.Status != "" {
			vuln.Status = req.Status
		}
		if req.Tags != "" {
			vuln.Tags = req.Tags
		}

		// 处理重新提交逻辑
		if req.ResubmittedAt != "" && req.ResubmittedBy != nil {
			if resubmittedTime, err := time.Parse(time.RFC3339, req.ResubmittedAt); err == nil {
				vuln.ResubmittedAt = &resubmittedTime
				vuln.ResubmittedBy = req.ResubmittedBy

				// 清除驳回相关信息
				vuln.RejectedAt = nil
				vuln.RejectedBy = nil
				vuln.RejectReason = ""

				// 注意：不在这里记录时间线，状态变更的时间线记录会在后面统一处理
			}
		}

	case "dev_engineer":
		// 研发工程师只能更新分配给自己的漏洞的状态
		if vuln.AssigneeID == nil || *vuln.AssigneeID != userID {
			// 检查是否是项目成员
			var memberCount int64
			db.Model(&models.ProjectMember{}).Where("project_id = ? AND user_id = ?", vuln.ProjectID, userID).Count(&memberCount)
			if memberCount == 0 {
				return nil, errors.New("无权限编辑此漏洞")
			}
		}

		// 研发工程师只能更新状态
		if req.Status != "" {
			// 验证状态是否有效
			validStatuses := []string{"unfixed", "fixing", "fixed", "rejected"}
			isValidStatus := false
			for _, status := range validStatuses {
				if req.Status == status {
					isValidStatus = true
					break
				}
			}
			if !isValidStatus {
				return nil, errors.New("研发工程师只能将状态设置为: 未修复、修复中、已修复、驳回")
			}

			// 记录状态变更时间
			now := time.Now().Truncate(time.Second)

			// 更新状态
			vuln.Status = req.Status

			// 根据状态变更设置相应的时间戳
			if req.Status == "fixing" && oldStatus != "fixing" {
				vuln.FixStartedAt = &now
				vuln.FixedBy = &userID
			} else if req.Status == "fixed" && oldStatus != "fixed" {
				vuln.FixedAt = &now
				vuln.FixedBy = &userID
			} else if req.Status == "retesting" && oldStatus != "retesting" {
				vuln.RetestAt = &now
				vuln.RetesterID = &userID
			} else if req.Status == "completed" && oldStatus != "completed" {
				vuln.CompletedAt = &now
				vuln.RetesterID = &userID
			} else if req.Status == "rejected" && oldStatus != "rejected" {
				vuln.RejectedAt = &now
				vuln.RejectedBy = &userID
				// 如果有驳回原因，保存到备注字段
				if req.RejectReason != "" {
					vuln.RejectReason = req.RejectReason
				} else if req.Comment != "" {
					vuln.RejectReason = req.Comment
				}
			}
		}

	default:
		return nil, errors.New("无权限编辑漏洞")
	}

	// 处理分配人变更（仅管理员和安全工程师可以修改）
	if (userRole == "super_admin" || userRole == "security_engineer") && req.AssigneeID != nil && (vuln.AssigneeID == nil || *vuln.AssigneeID != *req.AssigneeID) {
		if *req.AssigneeID != 0 {
			// 验证分配人是否存在
			var assignee models.User
			if err := db.Where("id = ?", *req.AssigneeID).First(&assignee).Error; err != nil {
				return nil, errors.New("指定的分配人不存在")
			}
			vuln.AssigneeID = req.AssigneeID
			s.addTimeline(vulnID, userID, "assigned", "漏洞重新分配")
		} else {
			vuln.AssigneeID = nil
			s.addTimeline(vulnID, userID, "unassigned", "取消漏洞分配")
		}
	}

	if err := db.Save(&vuln).Error; err != nil {
		return nil, errors.New("更新漏洞失败")
	}

	// 简化的时间线记录逻辑：只要状态发生变更就记录
	if req.Status != "" && oldStatus != req.Status {
		// 状态标签映射
		statusLabels := map[string]string{
			"pending":    "待处理",
			"unfixed":    "未修复",
			"fixing":     "修复中",
			"fixed":      "已修复",
			"retesting":  "复测中",
			"completed":  "已完成",
			"rejected":   "已驳回",
			"ignored":    "已忽略",
		}

		oldLabel := statusLabels[oldStatus]
		newLabel := statusLabels[req.Status]
		if oldLabel == "" {
			oldLabel = oldStatus
		}
		if newLabel == "" {
			newLabel = req.Status
		}

		// 构建描述信息
		description := fmt.Sprintf("状态从 %s 变更为 %s", oldLabel, newLabel)

		// 如果是驳回操作，添加驳回原因
		if req.Status == "rejected" && req.RejectReason != "" {
			description += fmt.Sprintf("，驳回原因：%s", req.RejectReason)
		}

		// 如果是重新提交操作，添加重新提交标识
		if req.ResubmittedAt != "" && req.ResubmittedBy != nil {
			description = fmt.Sprintf("重新提交：%s", description)
		}

		// 记录状态变更时间线
		s.addTimeline(vulnID, userID, "status_changed", description)
	}

	// 重新查询漏洞信息
	db.Preload("Asset").Preload("Project").Preload("Reporter").Preload("Assignee").Preload("Rejector").Preload("Resubmitter").Where("id = ?", vuln.ID).First(&vuln)

	// 发送状态变更邮件通知
	if req.Status != "" && oldStatus != req.Status {
		go func() {
			// 确定下一个处理人
			var nextUser *models.User
			var nextUserEmail string
			var nextUserName string

			switch req.Status {
			case "fixed":
				// 漏洞已修复，通知漏洞提交人进行复测
				if vuln.ReporterID != 0 {
					nextUser = &vuln.Reporter
				}
			case "retesting":
				// 复测中，通知原报告人
				if vuln.ReporterID != 0 {
					nextUser = &vuln.Reporter
				}
			case "completed":
				// 已完成，通知项目负责人
				if vuln.ProjectID != 0 && vuln.Project.OwnerID != 0 {
					nextUser = &vuln.Project.Owner
				}
			}

			if nextUser != nil && nextUser.Email != "" {
				nextUserEmail = nextUser.Email
				nextUserName = nextUser.RealName
				if nextUserName == "" {
					nextUserName = nextUser.Username
				}

				projectName := ""
				if vuln.ProjectID != 0 {
					projectName = vuln.Project.Name
				}

				if err := SendVulnStatusChangedNotification(vuln.Title, projectName, oldStatus, req.Status, nextUserName, nextUserEmail); err != nil {
					// 记录邮件发送失败的日志，但不影响漏洞更新
					fmt.Printf("发送漏洞状态变更通知邮件失败: %v\n", err)
				}
			}
		}()
	}

	// 更新项目统计信息
	if vuln.ProjectID != 0 {
		projectService := &ProjectService{}
		if err := projectService.UpdateProjectStats(vuln.ProjectID); err != nil {
			// 统计更新失败不影响漏洞更新，只记录错误
			// 可以考虑添加日志记录
		}
	}

	return &vuln, nil
}

// DeleteVuln 删除漏洞(软删除)
func (s *VulnService) DeleteVuln(vulnID uint, userID uint) error {
	db := Init.GetDB()

	var vuln models.Vulnerability
	if err := db.Where("id = ?", vulnID).First(&vuln).Error; err != nil {
		return errors.New("漏洞不存在")
	}

	// 记录项目ID用于后续更新统计
	projectID := vuln.ProjectID

	if err := db.Delete(&vuln).Error; err != nil {
		return errors.New("删除漏洞失败")
	}

	// 记录时间线
	s.addTimeline(vulnID, userID, "deleted", "漏洞已删除")

	// 更新项目统计信息
	if projectID != 0 {
		projectService := &ProjectService{}
		if err := projectService.UpdateProjectStats(projectID); err != nil {
			// 统计更新失败不影响漏洞删除，只记录错误
			// 可以考虑添加日志记录
		}
	}

	return nil
}

// GetVulnList 获取漏洞列表
func (s *VulnService) GetVulnList(req *VulnListRequest) (*VulnListResponse, error) {
	db := Init.GetDB()

	// 设置默认值
	if req.Page <= 0 {
		req.Page = 1
	}
	if req.PageSize <= 0 {
		req.PageSize = 10
	}

	query := db.Model(&models.Vulnerability{}).Preload("Asset").Preload("Project").Preload("Reporter").Preload("Assignee").Preload("Rejector").Preload("Resubmitter")

	// 基于角色的权限控制
	// 如果是查询特定项目的漏洞，需要先检查用户是否有项目权限
	if req.ProjectID != nil {
		// 检查用户是否有项目权限（管理员、项目负责人和项目成员都可以查看）
		if req.CurrentUserRole != "super_admin" {
			hasAccess := false

			// 检查是否是项目负责人
			var project models.Project
			if err := db.Where("id = ? AND owner_id = ?", *req.ProjectID, req.CurrentUserID).First(&project).Error; err == nil {
				hasAccess = true
			}

			// 如果不是项目负责人，检查是否是项目成员
			if !hasAccess {
				var memberCount int64
				db.Model(&models.ProjectMember{}).Where("project_id = ? AND user_id = ?", *req.ProjectID, req.CurrentUserID).Count(&memberCount)
				if memberCount > 0 {
					hasAccess = true
				}
			}

			if !hasAccess {
				// 用户既不是项目负责人也不是项目成员，不能查看项目漏洞
				return &VulnListResponse{
					Vulns:           []models.Vulnerability{},
					Vulnerabilities: []models.Vulnerability{},
					Total:           0,
					Page:            req.Page,
					PageSize:        req.PageSize,
				}, nil
			}
		}
		// 如果用户是项目负责人、项目成员或管理员，可以查看项目内所有漏洞，不添加额外的用户限制
	} else {
		// 查询全局漏洞列表时，应用原有的权限控制
		switch req.CurrentUserRole {
		case "security_engineer":
			// 安全工程师能看到自己创建的漏洞，以及自己负责的项目的漏洞
			query = query.Where("reporter_id = ? OR project_id IN (SELECT id FROM projects WHERE owner_id = ?) OR project_id IN (SELECT project_id FROM project_members WHERE user_id = ?)", req.CurrentUserID, req.CurrentUserID, req.CurrentUserID)
		case "dev_engineer":
			// 研发工程师能看到分配给自己的漏洞，以及自己负责的项目的漏洞
			query = query.Where("assignee_id = ? OR project_id IN (SELECT id FROM projects WHERE owner_id = ?) OR project_id IN (SELECT project_id FROM project_members WHERE user_id = ?)", req.CurrentUserID, req.CurrentUserID, req.CurrentUserID)
		case "super_admin":
			// 超级管理员能看到所有漏洞，不添加额外限制
		default:
			// 其他角色不能查看漏洞列表
			return &VulnListResponse{
				Vulns:           []models.Vulnerability{},
				Vulnerabilities: []models.Vulnerability{},
				Total:           0,
				Page:            req.Page,
				PageSize:        req.PageSize,
			}, nil
		}
	}

	// 添加过滤条件
	if req.Keyword != "" {
		// 支持关键词搜索，在标题、描述、CVE ID中搜索
		query = query.Where("title LIKE ? OR description LIKE ? OR cve_id LIKE ?",
			"%"+req.Keyword+"%", "%"+req.Keyword+"%", "%"+req.Keyword+"%")
	}
	if req.Title != "" {
		query = query.Where("title LIKE ?", "%"+req.Title+"%")
	}
	if req.VulnType != "" {
		query = query.Where("vuln_type = ?", req.VulnType)
	}
	if req.Severity != "" {
		query = query.Where("severity = ?", req.Severity)
	}
	if req.Status != "" {
		query = query.Where("status = ?", req.Status)
	}
	if req.Source != "" {
		query = query.Where("source = ?", req.Source)
	}
	if req.AssetID != nil {
		query = query.Where("asset_id = ?", *req.AssetID)
	}
	if req.ProjectID != nil {
		query = query.Where("project_id = ?", *req.ProjectID)
	}
	if req.ReporterID != nil {
		query = query.Where("reporter_id = ?", *req.ReporterID)
	}
	if req.AssigneeID != nil {
		query = query.Where("assignee_id = ?", *req.AssigneeID)
	}

	// 获取总数
	var total int64
	query.Count(&total)

	// 分页查询
	var vulns []models.Vulnerability
	offset := (req.Page - 1) * req.PageSize
	if err := query.Offset(offset).Limit(req.PageSize).Order("created_at DESC").Find(&vulns).Error; err != nil {
		return nil, errors.New("查询漏洞列表失败")
	}

	// 计算总页数
	totalPages := int((total + int64(req.PageSize) - 1) / int64(req.PageSize))

	return &VulnListResponse{
		Vulns:           vulns,
		Vulnerabilities: vulns, // 为前端兼容性提供同样的数据
		Total:           total,
		Page:            req.Page,
		PageSize:        req.PageSize,
		CurrentPage:     req.Page,
		TotalPages:      totalPages,
	}, nil
}

// AuditVuln 审核漏洞
func (s *VulnService) AuditVuln(vulnID uint, req *AuditRequest, userID uint) error {
	db := Init.GetDB()

	var vuln models.Vulnerability
	if err := db.Preload("Asset").Preload("Project").Preload("Reporter").Preload("Assignee").Where("id = ?", vulnID).First(&vuln).Error; err != nil {
		return errors.New("漏洞不存在")
	}

	if vuln.Status != "pending" {
		return errors.New("只能审核待确认的漏洞")
	}

	if req.Status != "confirmed" && req.Status != "rejected" {
		return errors.New("无效的审核状态")
	}

	oldStatus := vuln.Status
	vuln.Status = req.Status

	// 更新其他审核信息
	if req.Severity != "" {
		vuln.Severity = req.Severity
	}

	if req.AssigneeID != nil {
		vuln.AssigneeID = req.AssigneeID
	}

	if err := db.Save(&vuln).Error; err != nil {
		return errors.New("审核漏洞失败")
	}

	// 统一的状态变更时间线记录
	statusLabels := map[string]string{
		"pending":    "待处理",
		"confirmed":  "已确认",
		"rejected":   "已拒绝",
		"unfixed":    "未修复",
		"fixing":     "修复中",
		"fixed":      "已修复",
		"retesting":  "复测中",
		"completed":  "已完成",
		"ignored":    "已忽略",
	}

	oldLabel := statusLabels[oldStatus]
	newLabel := statusLabels[req.Status]
	if oldLabel == "" {
		oldLabel = oldStatus
	}
	if newLabel == "" {
		newLabel = req.Status
	}

	description := fmt.Sprintf("状态从 %s 变更为 %s", oldLabel, newLabel)
	s.addTimeline(vulnID, userID, "status_changed", description)

	// 发送审核结果邮件通知
	if nextUserID := s.getNextUserForStatus(&vuln, req.Status, req.AssigneeID); nextUserID != nil {
		s.sendVulnNotification(&vuln, oldStatus, req.Status, *nextUserID)
	}

	return nil
}

// FixVuln 标记漏洞为已修复
func (s *VulnService) FixVuln(vulnID uint, userID uint) error {
	db := Init.GetDB()

	var vuln models.Vulnerability
	if err := db.Preload("Asset").Preload("Project").Preload("Reporter").Preload("Assignee").Where("id = ?", vulnID).First(&vuln).Error; err != nil {
		return errors.New("漏洞不存在")
	}

	if vuln.Status != "confirmed" && vuln.Status != "fixing" {
		return errors.New("只能修复已确认的漏洞")
	}

	oldStatus := vuln.Status
	vuln.Status = "fixed"
	vuln.FixedBy = &userID
	now := time.Now().Truncate(time.Second)
	vuln.FixedAt = &now

	if err := db.Save(&vuln).Error; err != nil {
		return errors.New("标记修复失败")
	}

	// 统一的状态变更时间线记录
	statusLabels := map[string]string{
		"pending":    "待处理",
		"confirmed":  "已确认",
		"unfixed":    "未修复",
		"fixing":     "修复中",
		"fixed":      "已修复",
		"retesting":  "复测中",
		"completed":  "已完成",
		"rejected":   "已驳回",
		"ignored":    "已忽略",
	}

	oldLabel := statusLabels[oldStatus]
	newLabel := statusLabels["fixed"]
	if oldLabel == "" {
		oldLabel = oldStatus
	}

	description := fmt.Sprintf("状态从 %s 变更为 %s", oldLabel, newLabel)
	s.addTimeline(vulnID, userID, "status_changed", description)

	// 发送修复完成邮件通知给安全工程师进行复测
	if nextUserID := s.getNextUserForStatus(&vuln, "fixed", nil); nextUserID != nil {
		s.sendVulnNotification(&vuln, oldStatus, "fixed", *nextUserID)
	}

	return nil
}

// RetestVuln 复测漏洞
func (s *VulnService) RetestVuln(vulnID uint, result string, userID uint) error {
	db := Init.GetDB()

	var vuln models.Vulnerability
	if err := db.Preload("Asset").Preload("Project").Preload("Reporter").Preload("Assignee").Where("id = ?", vulnID).First(&vuln).Error; err != nil {
		return errors.New("漏洞不存在")
	}

	if vuln.Status != "fixed" {
		return errors.New("只能复测已修复的漏洞")
	}

	if result != "passed" && result != "failed" {
		return errors.New("无效的复测结果")
	}

	oldStatus := vuln.Status
	newStatus := ""
	if result == "passed" {
		vuln.Status = "closed"
		newStatus = "closed"
	} else {
		vuln.Status = "reopened"
		newStatus = "reopened"
	}

	if err := db.Save(&vuln).Error; err != nil {
		return errors.New("复测失败")
	}

	// 统一的状态变更时间线记录
	statusLabels := map[string]string{
		"pending":    "待处理",
		"confirmed":  "已确认",
		"unfixed":    "未修复",
		"fixing":     "修复中",
		"fixed":      "已修复",
		"retesting":  "复测中",
		"completed":  "已完成",
		"closed":     "已关闭",
		"reopened":   "重新开放",
		"rejected":   "已驳回",
		"ignored":    "已忽略",
	}

	oldLabel := statusLabels[oldStatus]
	newLabel := statusLabels[newStatus]
	if oldLabel == "" {
		oldLabel = oldStatus
	}
	if newLabel == "" {
		newLabel = newStatus
	}

	description := fmt.Sprintf("状态从 %s 变更为 %s", oldLabel, newLabel)
	if result == "passed" {
		description += "，复测通过"
	} else {
		description += "，复测失败"
	}

	s.addTimeline(vulnID, userID, "status_changed", description)

	// 发送复测结果邮件通知
	if nextUserID := s.getNextUserForStatus(&vuln, newStatus, nil); nextUserID != nil {
		s.sendVulnNotification(&vuln, oldStatus, newStatus, *nextUserID)
	}

	return nil
}

// AddComment 添加评论
func (s *VulnService) AddComment(vulnID uint, content string, userID uint) (*models.VulnComment, error) {
	db := Init.GetDB()

	// 验证漏洞是否存在
	var vuln models.Vulnerability
	if err := db.Where("id = ?", vulnID).First(&vuln).Error; err != nil {
		return nil, errors.New("漏洞不存在")
	}

	comment := models.VulnComment{
		VulnID:  vulnID,
		Content: content,
		UserID:  userID,
	}

	if err := db.Create(&comment).Error; err != nil {
		return nil, errors.New("添加评论失败")
	}

	// 重新查询评论信息(包含用户信息)
	db.Preload("User").Where("id = ?", comment.ID).First(&comment)

	return &comment, nil
}

// GetVulnStats 获取漏洞统计信息
func (s *VulnService) GetVulnStats() (map[string]interface{}, error) {
	db := Init.GetDB()

	var totalVulns int64
	var pendingVulns int64
	var confirmedVulns int64
	var fixedVulns int64
	var closedVulns int64

	db.Model(&models.Vulnerability{}).Count(&totalVulns)
	db.Model(&models.Vulnerability{}).Where("status = ?", "pending").Count(&pendingVulns)
	db.Model(&models.Vulnerability{}).Where("status = ?", "confirmed").Count(&confirmedVulns)
	db.Model(&models.Vulnerability{}).Where("status = ?", "fixed").Count(&fixedVulns)
	db.Model(&models.Vulnerability{}).Where("status = ?", "closed").Count(&closedVulns)

	// 按严重程度统计
	var severityStats []struct {
		Severity string `json:"severity"`
		Count    int64  `json:"count"`
	}
	db.Model(&models.Vulnerability{}).Select("severity, COUNT(*) as count").Group("severity").Scan(&severityStats)

	// 按类型统计
	var typeStats []struct {
		VulnType string `json:"vuln_type"`
		Count    int64  `json:"count"`
	}
	db.Model(&models.Vulnerability{}).Select("vuln_type, COUNT(*) as count").Group("vuln_type").Scan(&typeStats)

	return map[string]interface{}{
		"total_vulns":     totalVulns,
		"pending_vulns":   pendingVulns,
		"confirmed_vulns": confirmedVulns,
		"fixed_vulns":     fixedVulns,
		"closed_vulns":    closedVulns,
		"severity_stats":  severityStats,
		"type_stats":      typeStats,
	}, nil
}

// GetVulnTimeline 获取漏洞时间线
func (s *VulnService) GetVulnTimeline(vulnID uint) ([]models.VulnTimeline, error) {
	db := Init.GetDB()

	var timeline []models.VulnTimeline
	err := db.Where("vuln_id = ?", vulnID).
		Preload("User").
		Order("created_at ASC").
		Find(&timeline).Error

	if err != nil {
		return nil, errors.New("获取时间线失败")
	}

	return timeline, nil
}

// addTimeline 添加时间线记录
func (s *VulnService) addTimeline(vulnID uint, userID uint, action string, description string) {
	db := Init.GetDB()

	timeline := models.VulnTimeline{
		VulnID:      vulnID,
		Action:      action,
		Description: description,
		UserID:      userID,
	}

	if err := db.Create(&timeline).Error; err != nil {
		// 记录错误，但不影响主要业务流程
		fmt.Printf("Failed to create timeline record: %v\n", err)
	}
}

// sendVulnNotification 发送漏洞状态变更通知的统一方法
func (s *VulnService) sendVulnNotification(vuln *models.Vulnerability, oldStatus, newStatus string, nextUserID uint) {
	db := Init.GetDB()

	var nextUser models.User
	if err := db.First(&nextUser, nextUserID).Error; err != nil || nextUser.Email == "" {
		return // 用户不存在或没有邮箱，不发送通知
	}

	nextUserName := nextUser.RealName
	if nextUserName == "" {
		nextUserName = nextUser.Username
	}

	projectName := ""
	if vuln.ProjectID != 0 && vuln.Project.Name != "" {
		projectName = vuln.Project.Name
	}

	go func() {
		if err := SendVulnStatusChangedNotification(vuln.Title, projectName, oldStatus, newStatus, nextUserName, nextUser.Email); err != nil {
			// 记录邮件发送失败的日志，但不影响业务操作
			fmt.Printf("发送漏洞状态变更通知邮件失败: %v\n", err)
		}
	}()
}

// getNextUserForStatus 根据状态变更确定下一个处理人
func (s *VulnService) getNextUserForStatus(vuln *models.Vulnerability, newStatus string, assigneeID *uint) *uint {

	switch newStatus {
	case "confirmed":
		// 漏洞确认后，通知分配的研发工程师
		if assigneeID != nil {
			return assigneeID
		} else if vuln.AssigneeID != nil {
			return vuln.AssigneeID
		}
	case "rejected":
		// 漏洞拒绝后，通知原报告人
		if vuln.ReporterID != 0 {
			return &vuln.ReporterID
		}
	case "fixed":
		// 漏洞已修复，通知漏洞提交人进行复测
		if vuln.ReporterID != 0 {
			return &vuln.ReporterID
		}
	case "closed":
		// 复测通过，通知项目负责人
		if vuln.ProjectID != 0 && vuln.Project.OwnerID != 0 {
			return &vuln.Project.OwnerID
		}
		// 如果没有项目负责人，通知原报告人
		if vuln.ReporterID != 0 {
			return &vuln.ReporterID
		}
	case "reopened":
		// 复测失败，通知分配的研发工程师重新修复
		if vuln.AssigneeID != nil {
			return vuln.AssigneeID
		}
		// 如果没有分配人，通知原报告人
		if vuln.ReporterID != 0 {
			return &vuln.ReporterID
		}
	}

	return nil
}
